/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#include "StdAfx.h"
#include <iostream>
#include "EntityStates.h"
#include "IEntity.h"
#include "DialogModel.h"

#include "../kernel.h"

extern Kernel* g_kernel;
#define TIME g_kernel->GetTime()


/**
=====================================
Base State Class - Run a script and/or play
a sound entering a state
=====================================
*/
void State::Enter(IEntity* ent) 
{
    // play a sound going into the
    // state
    if ( m_sound ) {
        m_sound->SetPosition( ent->m_physObject.GetPosition() );
        m_sound->Play(false); 
    }

    // run a script
    if ( m_scriptFile != "" )
    {
        g_kernel->GetScriptEngine()->RunFile( m_scriptFile );
    }

    ent->m_nextUpdate = TIME + m_nextUpdate;
}

/**
==================
Walking State
=================
*/
void WalkState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 10;
    //ent->m_nextUpdate = TIME + m_nextUpdate;
}



/**
==================
idle State
=================
*/
void IdleState::Exec(IEntity *ent)
{
    ent->m_direction.ZeroOut();
    ent->m_gravity = 0;
    ent->m_heightAboveGround = 0;

    Vector2f position = ent->m_physObject.GetPosition();
    ent->UpdateCollisionBounds( position.x, position.y );
}

/**
==================
Attack State
=================
*/
void AttackState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 10;
    //std::cout << "Executing attack " << m_nextUpdate << "\n";
    //ent->m_nextUpdate = TIME + m_nextUpdate;
}

/**
==================
Hit State
=================
*/
void HitState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 10;
    //ent->m_nextUpdate = TIME + m_nextUpdate;
}

/**
==================
Dead State
=================
*/
void DeadState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 450;
    //ent->m_nextUpdate = TIME + m_nextUpdate;
    ent->SetRemove(true);
}


/**
==================
ThrowingState
=================
*/
void ThrowingState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + m_nextUpdate;
    //ent->m_nextUpdate = TIME + 10;
    //if ( ent->CarryingEntity() )
    //{
    //    m_carriedent->SetState( ENT_STATES[THROWN] );
    //    Vector2f thrownTo;
    //    thrownTo.ZeroOut();
    //    int dest = 2.3;

    //    switch( GetFace() )
    //    {
    //    case NORTH: thrownTo.y -= dest; break;
    //    case EAST:  thrownTo.x += dest; break;
    //    case SOUTH: thrownTo.y += dest; break;
    //    case WEST:  thrownTo.x -= dest; break;
    //    }
    //    m_carriedent->m_heightAboveGround = 32;
    //    m_carriedent->MoveToOverTime( thrownTo, TIME + 500 );

    //    m_carriedent->m_carrier = NULL;
    //    m_carriedent = NULL;

    //    m_nextUpdate = TIME + 100;
    //}
}

/**
==================
Thrown State
=================
*/
void ThrownState::Enter( IEntity *ent )
{
    State::Enter( ent );
    Vector2f position = ent->m_physObject.GetPosition();
    ent->UpdateCollisionBounds( position.x, position.y ); 
}
void ThrownState::Exec(IEntity* ent) 
{
    if ( ent->ArrivedToLocation() ) 
    {
        ent->SetState( ENT_STATES[IDLE] );
    }
    else
    {
        Vector2f position = ent->m_physObject.GetPosition();
        ent->UpdateCollisionBounds( position.x, position.y );
    }
}

/**
==================
Talk State
=================
*/
void TalkState::Enter(IEntity* p) 
{   
    if ( g_kernel->GetGame()->GetCurrentState()->GetName() != "DialogState" )
    {    
        g_kernel->GetScriptEngine()->RunFile( p->m_attributes.GetStr("dialog") );
    }
}


/**
==================
CarryingState
=================
*/
void CarryingState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 10;
    //ent->m_nextUpdate = TIME + m_nextUpdate;
}


/**
==================
Carried State
=================
*/
void CarriedState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + m_nextUpdate;

    IEntity* carrier = ent->CarriedBy();
    if ( carrier )
    {
        // TODO - fix moveto
        // ent->MoveTo( carrier->m_world );
        ent->m_physObject.SetPosition( carrier->m_physObject.GetPosition() );

        Vector2f position = ent->m_physObject.GetPosition();
        position.y -= 16;
            
        ent->UpdateCollisionBounds( position.x, position.y );
        ent->m_nextUpdate = 0;
    } 
}

void CarriedState::Exit(IEntity* p) {  
    Vector2f pos = p->m_physObject.GetPosition();
    p->UpdateCollisionBounds( (int)pos.x, (int)pos.y );
};

/**
==================
CarryingWalkingState
=================
*/
void CarryingWalkingState::Exec(IEntity* ent) 
{
    //ent->m_nextUpdate = TIME + 10;
    //ent->m_nextUpdate = TIME + m_nextUpdate;
}



